#ifndef _QANSIBUFFER_H
#define _QANSIBUFFER_H


#include "qansieditor.h"
#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QPoint>
#include <QtCore/QRect>
#include <QtCore/QList>


namespace QAnsiEditor {


class QAnsiLine;


/**
 * This class represents all lines used in ANSI widget.
 *
 * @author gonwan (gonwan at gmail dot com)
 */
class QAnsiBuffer
{

public:
    /**
     * Constructor
     * @param iRow The row count
     * @param iColumn The column count
     */
    QAnsiBuffer(/*in*/ int iRow, /*in*/ int iColumn);
    /**
     * Destructor
     */
    ~QAnsiBuffer();
    /**
     * Get row count
     * @return The row count
     */
    int getRowCount() const;
    /**
     * Get column count
     * @return The column count
     */
    int getColumnCount() const;

    /**
     * Get the line by given row index
     * @param iIndex The row index
     * @return The ansi line instance
     */
    QAnsiLine *at(/*in*/ int iIndex) const;
    /**
     * Append string content in current cursor position
     * This function is used in the ansi decoder class.
     * @param strText The string content
     */
    void appendTextContent(/*in*/ const QString &strText);

    /**
     * Get X of cursor
     * @return X
     */
    int getCursorX() const;
    /**
     * Get Y of cursor
     * @return Y
     */
    int getCursorY() const;
    /**
     * Set X and Y of cursor
     * @param iX The X
     * @param iY The Y
     */
    void setCursor(/*in*/ int iX, /*in*/ int iY);
    /**
     * Move cursor using offsets
     * @param iOffsetX The offset in X
     * @param iOffsetY The offset in Y
     */
    void moveCursor(/*in*/ int iOffsetX, /*in*/ int iOffsetY);
    /**
     * Save cursor position temporarily
     * It is used to deal with "*[s" sequence
     */
    void saveCursor();
    /**
     * Restore temporarily saved cursor position
     * It is used to deal with "*[u" sequence
     */
    void restoreCursor();

    /**
     * Save current color and effect temporarily
     * It is used to display a multi-byte character that has more than one attribute.
     */
    void saveAttribute();
    /**
     * Restore temporarily saved color and effect
     * It is used to display a multi-byte character that has more than one attribute.
     */
    void restoreAttribute();

    /**
     * Get current color
     * @return The current color
     */
    char getCurrentColor() const;
    /**
     * Set current color
     * @param chColor The color to set
     */
    void setCurrentColor(/*in*/ char chColor);
    /**
     * Get current effect
     * @return The current effect
     */
    char getCurrentEffect() const;
    /**
     * Set current effect
     * @param chEffect The color to set
     */
    void setCurrentEffect(/*in*/ char chEffect);

    /**
     * Erase from current cursor position to the begin of current line
     */
    void eraseToLineBegin();
    /**
     * Erase from current cursor position to the end of current line
     */
    void eraseToLineEnd();
    /**
     * Erase the whole line where the cursor is currently located
     */
    void eraseEntireLine();

    /**
     * Erase from current cursor position to the begin of screen
     */
    void eraseToScreenBegin();
    /**
     * Erase from current cursor position to the end of screen
     */
    void eraseToScreenEnd();
    /**
     * Erase the whole screen
     */
    void eraseEntireScreen();
    
    /**
     * Insert lines at cursor
     * @param iCount The count
     */
    void insertLine(int iCount);
    /**
     * Delete lines at cursor
     * @param iCount The count
     */
    void deleteLine(int iCount);

    /**
     * Get selection area from 2 points
     * Assertions are used to check valid parameters.
     * @param ppt1 The 1st point
     * @param ppt2 The 2nd point
     * @return true if there is a selection area
     */
    bool getSelection(/*out*/ QPoint *ppt1, /*out*/ QPoint *ppt2);
    /**
     * Set selection area by 2 points
     * Assertions are used to check valid parameters.
     * @param pt1 The 1st point
     * @param pt2 The 2nd point
     * @return true if a repaint is needed
     */
    bool setSelection(/*in*/ const QPoint &pt1, /*in*/ const QPoint &pt2);
    /**
     * Clear current selection area
     */
    void clearSelection();
    /**
     * Whether the given point is in selection area
     * @param pt The point
     * @return true if it is
     */
    bool isSelected(/*in*/ const QPoint &pt) const;
    /**
     * Get selected text
     * @param bColor Whether deal with colors
     * @param strEscape alternative ESC key
     * @return The selected text
     */
    QString getSelectedText(/*in*/ bool bColor, /*in*/ const QString &strEscape="\x1b\x1b") const;
    /**
     * Get encoded selected text
     * To support one-char-two-color characters, we return a byte array in current output encoding.
     * @param bColor Whether deal with colors
     * @param strEscape alternative ESC key
     * @return The byte array of selected text
     */
    QByteArray getEncodedSelectedText(/*in*/ QTextCodec *pCodec, /*in*/ const QString &strEscape="\x1b\x1b") const;
    /**
     * Set color and effect of selected text
     * For performance issue, we merge color and effect setting into one function.
     * @param chColor Color to set
     * @param chEffect Effect to set
     */
    void setAttributeOfSelectedText(/*in*/ char chColor=-1, /*in*/ char chEffect=-1);
    /**
     * Scroll all lines by a given count at a given position
     * If iCount > 0, scroll up
     * If iCount < 0, scroll down
     * @param iStart The start
     * @param iCount The count
     */
    void scrollLines(/*in*/ int iStart, /*in*/ int iCount);

private:
    /** Row count */
    int m_iRow;
    /** Column count */
    int m_iColumn;
    /** List of all ansi line instance */
    QList<QAnsiLine *>  m_ansiLineList;
    /** X of current cursor position */
    int m_iCursorX;
    /** Y of current cursor position */
    int m_iCursorY;
    /** Temporarily saved X cursor position to deal with "*[s" and "*[u" sequence */
    int m_iSavedCursorX;
    /** Temporarily saved Y cursor position to deal with "*[s" and "*[u" sequence */
    int m_iSavedCursorY;
    /** Temporarily saved X cursor position to display a multi-byte character that has more than one attribute */
    int m_iHackingCursorX;
    /** Temporarily saved Y cursor position to display a multi-byte character that has more than one attribute */
    int m_iHackingCursorY;
    /** Current color for drawing */
    char m_chCurrentColor;
    /** Current effect for drawing */
    char m_chCurrentEffect;
    /** Temporarily saved color to display a multi-byte character that has more than one attribute */
    char m_chHackingColor;
    /** Temporarily saved effect to display a multi-byte character that has more than one attribute */
    char m_chHackingEffect;
    /** Rectangle selection? */
    bool m_bRect;
    /** Point marking the start of selection, (-1, -1) if no selection */
    QPoint m_ptSelStart;
    /** Point marking the end of selection, (-1, -1) if no selection */
    QPoint m_ptSelEnd;
    /** Cache use for rectangle selection, same as the combination of selection start and end */
    QRect m_rcSel;

    /**
     * Clear a rectangle area with current color and effect
     * Assertions are used to check valid parameters.
     * @param iX The X
     * @param iY The Y
     * @param iWidth The width
     * @param iHeight The height
     */
    void clearArea(/*in*/ int iX, /*in*/ int iY, /*in*/ int iWidth, /*in*/ int iHeight);
};


}  // namespace QAnsiEditor


#endif  // _QANSIBUFFER_H
